using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;

namespace rlTodayMakeSkin.Project.XmlElement
{
    public class rlTodayXmlElementCollection : ICollection

    {

        /*****************
         FIELDS
         *******************/
        private int intCount = 0;
        private rlTodayXmlCollectionItem lista = null;

        /*********************
         COSNTRUCTORS
         *********************/
        public rlTodayXmlElementCollection()
        {
         
        }

        /// <summary>
        /// adds a new element to the collection
        /// </summary>
        /// <param name="element"></param>
        public void Add(rlTodayXmlElement element)
        {
            if (lista == null)
                lista = new rlTodayXmlCollectionItem(element, null);
            else
            {
                rlTodayXmlCollectionItem tmp = new rlTodayXmlCollectionItem(element, lista);
                lista = tmp;
            }
            intCount++;

        }

        /// <summary>
        /// removes specificated object from the collection
        /// </summary>
        /// <param name="element"></param>
        public void remove(rlTodayXmlElement element)
        {
            lista = removeObject(lista, element);
            intCount--;
        }

        public rlTodayXmlElement this[int position]
        {
            get {
                if (position > intCount) throw new IndexOutOfRangeException("Specificated position is larger than length of the collection");
                return GetElementAt(lista,position); 
            }
        }

        /// <summary>
        /// removes element at specificated position
        /// </summary>
        /// <param name="index"></param>
        public void remove(int index)
        {
            lista = removeFromIndex(lista, index);
            intCount--;
        }

        /**********************************
         IMPLEMENTATIONS OF ICollection INTERFACE
         *********************************/

        /// <summary>
        /// copy collection in an array from specificated index
        /// </summary>
        /// <param name="array"></param>
        /// <param name="index"></param>
        /// <remarks>NOT YET IMPLEMENTED!</remarks>
        public void CopyTo(Array array, int index)
        {

            throw new Exception("This method is not yet implemented");
        }

        public rlTodayXmlElement[] ToArray()
        {
            rlTodayXmlElement[] ars = new rlTodayXmlElement[intCount];
            addsElToArrayFrom(lista, ars, 0, 0);
            return ars;
        }

        /// <summary>
        /// gets number of elements in this collection
        /// </summary>
        public int Count
        {
            get { return intCount; }
        }

        public bool IsSynchronized
        {
            get { return false; }
        }

        public object SyncRoot
        {
            get { throw new Exception("The method or operation is not implemented."); }
        }


        public IEnumerator GetEnumerator()
        {
            return new MyEnumerator(lista);
        }

        /****************
         PRIVATE FIELDS
         ***************/
        private void addsElToArrayFrom(rlTodayXmlCollectionItem lista, rlTodayXmlElement[] arr, int start, int curIndex){
        /*adds element to array starting from start index of the collection
         Parameters:
         - lista: collection
         - arr: current array to populate
         - start: index of the element in the collection from which fill array
         - curIndex: current index of the array arr that can be fill with element of the list*/
            if (start > 0) addsElToArrayFrom(lista.nextItem, arr, --start, curIndex);
            if (lista == null) return;
            arr[curIndex] = lista.currentItem;
            addsElToArrayFrom(lista.nextItem, arr, 0, ++curIndex);
        }

        private rlTodayXmlCollectionItem removeObject(rlTodayXmlCollectionItem lista, rlTodayXmlElement objToRemove)
        //removes specificated object from the collection
        {
            if (lista.currentItem == objToRemove) return lista.nextItem;
            if (lista.nextItem == null) return null;
            lista.nextItem = removeObject(lista.nextItem, objToRemove);
            return lista;
        }

        private rlTodayXmlCollectionItem removeFromIndex(rlTodayXmlCollectionItem lista, int index)
        //removes object from the collection at specificated position
        {
            if (index == 0) return lista.nextItem;
            if (lista.nextItem == null) return null;
            lista.nextItem = removeFromIndex(lista.nextItem, --index);
            return lista;
        }

        private rlTodayXmlElement GetElementAt(rlTodayXmlCollectionItem lista, int position)
        {
            if (position == 0) return lista.currentItem;
            return GetElementAt(lista.nextItem, --position);
        }

        /*********************************
         * PRIVATE CLASSES
         * ******************************/

        /*Private class that represents the base element for the collection*/
        private class rlTodayXmlCollectionItem
        {
            private rlTodayXmlCollectionItem next;
            private rlTodayXmlElement current;

            public rlTodayXmlCollectionItem(rlTodayXmlElement curElement, rlTodayXmlCollectionItem next)
            {
                current = curElement;
                this.next = next;
            }

            public rlTodayXmlCollectionItem nextItem
            {
                get { return next; }
                set { next = value; }
            }

            public rlTodayXmlElement currentItem
            {
                get { return current; }
                set { current = value; }
            }
        }

        //Private class that represents the enumrator for this collection
        private class MyEnumerator : IEnumerator
        {

            rlTodayXmlCollectionItem pointer;
            rlTodayXmlCollectionItem first;

            public MyEnumerator(rlTodayXmlCollectionItem first)
            {
                this.first = first;
            }

            object IEnumerator.Current
            {
                get { return pointer.currentItem; }
            }

            bool IEnumerator.MoveNext()
            {
                if (pointer==null || pointer.nextItem == null) return false;
                pointer = pointer.nextItem;
                return true;
            }

            void IEnumerator.Reset()
            {
                pointer = first;
            }
        }

        
    }//end class
}//end namespace
